<template>
  <div class="ad-chart-w">
    <slot name="header">
      <div class="flex-c-sb">
        <p>指标趋势</p>
        <a-popover trigger="click" position="br">
          <a-button type="text">
            预览指标设置
            <icon-down />
          </a-button>
          <template #content>
            <a-scrollbar style="height: 500px; overflow-y: auto">
              <ul>
                <li @click="changeTargetState(target)" class="all-target" :class="{ active: targetShowKeys.includes(target.key) }" v-for="(target, i) in allTargetKeys" :key="i">
                  <p>
                    <span>{{ target.name }}</span>
                    <a-popover :content="target.tip">
                      <icon-question-circle />
                    </a-popover>
                  </p>
                  <p v-if="target.type == 'price'">
                    <span class="code">USD</span>
                    <span>{{ formatVal(target) }}</span>
                  </p>
                  <p v-else-if="target.type == 'percentage'">
                    <span>{{ formatVal(target) }}%</span>
                  </p>
                  <p v-else>{{ formatVal(target) }}</p>
                  <p class="explain">{{ ['acos', 'impressions', 'clicks', 'purchasesOrder', 'saleAmount'].includes(target.key) ? '合计' : '平均' }}</p>
                </li>
              </ul>
            </a-scrollbar>
          </template>
        </a-popover>
      </div>
    </slot>
    <ul class="flex-c flex-wrap" v-if="advertStore.targetClickKeys">
      <template v-for="(target, i) in allTargetKeys" :key="i">
        <li class="all-target show-target" :style="{ borderColor: advertStore.targetClickKeys.includes(target.key) ? target.color : 'transparent' }" v-if="targetShowKeys.includes(target.key)" @click="changeTargetClick(target)">
          <p>
            <span>{{ target.name }}</span>
          </p>
          <p v-if="target.type == 'price'">
            <span class="code">USD</span>
            <span>{{ formatVal(target) }}</span>
          </p>
          <p v-else-if="target.type == 'percentage'">
            <span>{{ formatVal(target) }}%</span>
          </p>
          <p v-else>{{ formatVal(target) }}</p>
          <p class="explain">{{ ['acos', 'impressions', 'clicks', 'purchasesOrder', 'saleAmount'].includes(target.key) ? '合计' : '平均' }}</p>
          <p class="delete-icon" @click.stop="changeTargetState(target)"><icon-close /></p>
        </li>
      </template>
    </ul>
    <div ref="adChartFef" v-if="advertStore.targetClickKeys && advertStore.targetClickKeys.length" :style="{ height: height + 'px' }"></div>
  </div>
</template>
<script lang="ts" setup>
  import useEcharts from '@/hooks/useEcharts'
  import { ref, onMounted, computed, nextTick, onBeforeUnmount, getCurrentInstance } from 'vue'
  import { portfoliosMetrics, portfoliosTrendCharts, adProductMetrics, adProductTrendCharts, targetingTrendCharts, targetingMetrics, keywordMetrics, keywordTrendCharts, campaignMetrics, campaignTrendCharts, adGroupMetrics, adGroupTrendCharts, searchTermMetrics, searchTermTrendCharts } from '@/api/advert'
  import { dispose } from 'echarts/core'
  import useAdvertStore from '@/store/modules/advert'
  const props = defineProps({
    searchParams: {
      type: Object,
      default: () => {},
    },
    type: {
      type: String,
      default: 'portfolio',
    },
    height: {
      type: [String, Number],
      default: 200,
    },
  })
  const apiMap = {
    metrics: {
      portfolio: portfoliosMetrics,
      campaign: campaignMetrics,
      adGroup: adGroupMetrics,
      keyword: keywordMetrics,
      product: adProductMetrics,
      searchTerm: searchTermMetrics,
      targeting: targetingMetrics,
    },
    charts: {
      portfolio: portfoliosTrendCharts,
      campaign: campaignTrendCharts,
      adGroup: adGroupTrendCharts,
      keyword: keywordTrendCharts,
      product: adProductTrendCharts,
      searchTerm: searchTermTrendCharts,
      targeting: targetingTrendCharts,
    },
  }
  const advertStore = useAdvertStore()
  const chartDatas = ref<Array<any>>([])
  const { proxy } = getCurrentInstance()
  const targetList = ref<any>({
    cost: {
      key: 'cost',
      name: '花费',
      type: 'price',
      tip: '亚马逊广告花费',
      color: '#91cc75',
    },
    impressions: {
      key: 'impressions',
      name: '曝光量',
      type: 'num',
      tip: '广告曝光次数',
      color: '#5470c6',
    },
    clicks: {
      key: 'clicks',
      name: '点击量',
      type: 'num',
      tip: '广告点击次数',
      color: '#fac858',
    },
    ctr: {
      key: 'ctr',
      name: '点击率CTR',
      type: 'percentage',
      tip: '广告点击转化率，CTR=点击量/曝光量',
      color: '#ee6666',
    },
    cpc: {
      key: 'cpc',
      name: '单次点击成本CPC',
      type: 'price',
      tip: '单次点击成本，CPC=广告花费/点击量',
      color: '#73c0de',
    },
    saleAmount: {
      key: 'saleAmount',
      name: '广告销售额',
      type: 'price',
      tip: '广告带来的销售额及关联销售额',
      color: '#3ba272',
    },
    purchasesOrder: {
      key: 'purchasesOrder',
      name: '广告订单量',
      type: 'num',
      tip: '广告带来的订单及关联订单数量',
      color: '#fc8452',
    },
    acos: {
      key: 'acos',
      name: '投入产出比ACOS',
      type: 'percentage',
      tip: '投入产出比，ACOS=广告花费/广告销售额*100%',
      color: '#9a60b4',
    },
    roas: {
      key: 'roas',
      name: '支出回报ROAS',
      type: 'num',
      tip: '支出回报，ROAS=广告销售额/广告花费',
      color: '#ea7ccc',
    },
    cvr: {
      key: 'cvr',
      name: '广告转化率CVR',
      type: 'percentage',
      tip: '广告转化率，CVR=广告订单量/点击量*100%',
      color: '#a3beff',
    },
    cpa: {
      key: 'cpa',
      name: '单笔订单平均广告花费CPA',
      type: 'price',
      tip: '单笔订单平均广告花费，CPA=广告花费/广告订单量',
      color: '#ffcaaf',
    },
  })
  const allTargetKeys = ref<Array<any>>(Object.values(targetList.value))
  const targetShowKeys = computed(() => advertStore.targetShowKeys || [])
  // 设置预览指标
  function changeTargetState(item: any) {
    let targetKeys = [...advertStore.targetShowKeys]
    let _index = targetKeys.indexOf(item.key)
    if (_index > -1) {
      targetKeys.splice(_index, 1)
      if (advertStore.targetClickKeys.indexOf(item.key) > -1) {
        changeTargetClick(item)
      }
    } else {
      targetKeys.push(item.key)
    }
    advertStore.changeTargetShowKey(targetKeys)
  }
  // 设置需要展示的图表-只展示2个
  function changeTargetClick(item: any) {
    let targetClickKeys = [...advertStore.targetClickKeys]
    let _index = targetClickKeys.indexOf(item.key)
    if (_index > -1) {
      targetClickKeys.splice(_index, 1)
    } else if (targetClickKeys.length == 2) {
      targetClickKeys.splice(0, 1)
      targetClickKeys.push(item.key)
    } else {
      targetClickKeys.push(item.key)
    }
    advertStore.changeTargetClickKey(targetClickKeys)
    nextTick(() => {
      initChart()
    })
  }
  // 数量多以万为单位
  function formatVal(item: any) {
    let val = item.value || 0
    if (val < 100000) {
      return Number(val)
    } else {
      return Number(val / 10000).toFixed(2) + '万'
    }
  }

  // 刷新数据
  async function refreshData() {
    await getTargetList()
    await getChartData()
    nextTick(() => {
      initChart()
    })
  }
  // 获取所有指标概览数据
  async function getTargetList() {
    if (!props.searchParams.startDate) return
    const res: any = await apiMap.metrics[props.type](props.searchParams)
    if (res?.data) {
      Object.keys(targetList.value).forEach((key) => {
        targetList.value[key].value = res.data[key]
      })
    }
  }
  // 获取所有指标图表数据
  let dates: Array<any> = []
  let yDataMap = {}
  async function getChartData() {
    if (!props.searchParams.startDate) return
    const res: any = await apiMap.charts[props.type](props.searchParams)
    chartDatas.value = res?.data || []
    dates = chartDatas.value.map((el) => proxy.$setTime(el.reportDate, 'MM-DD'))
    Object.keys(targetList.value).forEach((key) => {
      yDataMap[key] = chartDatas.value.map((el) => el[key])
    })
  }

  const adChartFef = ref<HTMLDivElement | null>(null)
  // 获取series轴信息
  function setSeries() {
    return advertStore.targetClickKeys?.map((key, index) => {
      return {
        name: targetList.value[key]?.name,
        yAxisIndex: index,
        type: key == 'impressions' ? 'bar' : 'line',
        data: yDataMap[key],
        color: targetList.value[key]?.color,
      }
    })
  }
  // 获取Y轴信息
  function setYData() {
    return advertStore.targetClickKeys?.map((key) => {
      let max = Math.max.apply(null, yDataMap[key] || [])
      return {
        type: 'value',
        name: targetList.value[key]?.name,
        min: 0,
        max: setMaxInterval(max).max,
        splitNumber: 5,
        minInterval: 1,
        nameGap: 20,
        interval: setMaxInterval(max).interval,
        axisLine: {
          show: true,
          lineStyle: {
            color: targetList.value[key]?.color,
          },
        },
        axisLabel: {
          formatter(v: any) {
            v = v.toString()
            if (Math.abs(v) >= 100000) {
              return v / 10000 + '万'
            } else {
              return v
            }
          },
        },
      }
    })
  }
  // 为了平均分布Y轴
  function setMaxInterval(max: number) {
    if (max <= 1) {
      return { max: 1, interval: 0.2 }
    }
    if (max <= 5) {
      return { max: 5, interval: 1 }
    }
    if (max <= 10) {
      return { max: 10, interval: 2 }
    }
    if (max <= 50) {
      return { max: 50, interval: 10 }
    }
    if (max <= 100) {
      return { max: 100, interval: 20 }
    }
    if (max <= 500) {
      return { max: 500, interval: 100 }
    }
    if (max <= 1000) {
      return { max: 1000, interval: 200 }
    }
    if (max <= 2000) {
      return { max: 2000, interval: 400 }
    }
    if (max <= 5000) {
      return { max: 5000, interval: 1000 }
    }
    if (max <= 8000) {
      return { max: 8000, interval: 1600 }
    }
    if (max <= 10000) {
      return { max: 10000, interval: 2000 }
    }
    if (max <= 20000) {
      return { max: 20000, interval: 4000 }
    }
    if (max <= 50000) {
      return { max: 50000, interval: 10000 }
    }
    if (max <= 80000) {
      return { max: 80000, interval: 16000 }
    }
    if (max <= 100000) {
      return { max: 100000, interval: 20000 }
    }
    if (max <= 500000) {
      return { max: 500000, interval: 100000 }
    }
    if (max <= 1000000) {
      return { max: 1000000, interval: 200000 }
    }
    if (max <= 2000000) {
      return { max: 2000000, interval: 400000 }
    }
    if (max <= 5000000) {
      return { max: 5000000, interval: 1000000 }
    }
    if (max <= 10000000) {
      return { max: 10000000, interval: 2000000 }
    }
    if (max <= 50000000) {
      return { max: 50000000, interval: 10000000 }
    }
    return {
      max: Math.ceil(max / 5) * 5,
      interval: Math.ceil(max / 5),
    }
  }
  function initChart() {
    // 容易导致重复渲染，先清除
    if (adChartFef.value) {
      dispose(adChartFef.value as HTMLDivElement)
    }
    if (!advertStore.targetClickKeys?.length) return
    const option = {
      grid: {
        left: 50,
        top: 40,
        bottom: 10,
        right: 50,
        containLabel: true,
      },
      tooltip: {
        trigger: 'axis',
        valueFormatter: (v: number) => {
          if (Math.abs(v) >= 100000) {
            return (v / 10000).toFixed(2) + '万'
          } else {
            return v
          }
        },
      },
      xAxis: {
        type: 'category',
        data: dates,
        axisLine: {
          show: true,
          lineStyle: {
            color: '#98A3B2',
            width: 0,
            type: 'solid',
          },
        },
        axisTick: {
          show: false,
        },
      },
      yAxis: setYData(),
      series: setSeries(),
    }
    nextTick(() => useEcharts(adChartFef.value as HTMLDivElement).setOption(option))
  }
  onMounted(initChart)
  onBeforeUnmount(() => {
    if (adChartFef.value) dispose(adChartFef.value as HTMLDivElement)
  })

  defineExpose({ refreshData })
</script>
<style lang="less" scoped>
  .ad-chart-w {
    background-color: #fff;
    padding: 0 10px 10px;
  }
  .all-target {
    width: 200px;
    margin-bottom: 5px;
    border: 1px solid var(--color-border);
    height: 60px;
    background-color: var(--color-fill-1);
    padding: 4px;
    position: relative;
    &.active {
      border-color: rgba(var(--primary-6), 0.4);
      color: rgba(var(--primary-6), 0.8);
      .arco-icon {
        color: rgba(var(--primary-6), 0.8);
      }
    }
    .arco-icon {
      font-size: 14px;
      color: #666;
      margin-left: 2px;
    }
  }
  .code {
    display: inline-block;
    padding: 2px;
    color: #fff;
    line-height: 1;
    font-size: 12px;
    transform: scale(0.7);
    background-color: rgba(var(--primary-5), 0.5);
  }
  .explain {
    position: absolute;
    right: 5px;
    bottom: 4px;
    color: #999;
    font-size: 12px;
  }
  .show-target {
    margin-right: 10px;
    width: 160px;
    height: 50px;
    border: none;
    border-top: 2px solid transparent;
    font-size: 12px;
    .delete-icon {
      position: absolute;
      top: 2px;
      cursor: pointer;
      right: 5px;
    }
  }
</style>
